home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / NDK / NDK_1.3 / Read-Me1.3 / 1.2ReadMes / libraries / Intuition < prev    next >
Encoding:
Text File  |  1988-07-26  |  48.0 KB  |  1,342 lines

  1.  
  2.  INTUITION VERSION 33 (v1.2 AMIGA SYSTEM SOFTWARE RELEASE)
  3.              Jim Mackraz, Commodore-Amiga, Inc.
  4.  
  5. 1. INTUITION
  6.    =========
  7.  
  8. This document describes changes and key observations for the
  9. revision to Intuition which is part of the v1.2 Kickstart or
  10. ROM software.
  11.  
  12. This exposition is directed at the software developer who is
  13. already  familiar  with  the Intuition library, who has read
  14. the Intuition Reference Manual carefully in the  areas  dis-
  15. cussed.   Particular familiarity is assumed of the usage and
  16. methods of the Intuition Direct Communication  Message  Port
  17. (IDCMP).
  18.  
  19. The "autodocs" are a reference resource  for  Intuition  and
  20. the  entire  system.  Autodocs are function description sec-
  21. tions, which are automatically  extracted  from  the  source
  22. itself.   An entry in the Intuition autodocs (intuition.doc)
  23. might be written as "the BeginRefresh() autodocs."  A refer-
  24. ence  to  a function description in the Layers library might
  25. be layers.library/BeginUpdate() or layers/BeginUpdate().
  26.  
  27. The autodocs appear in volume 2 of the  Rom  Kernel  manual,
  28. but the most up-to-date versions are released on a disk with
  29. the developers' distribution of the system software.
  30.  
  31. Many technical aspects of Intuition relate  closely  to  the
  32. Layers  library, which supports clipping and saving of offs-
  33. creen areas of windows.  It is very useful to understand the
  34. basics  of  this  library, but it should be rarely, if ever,
  35. used by an application program directly.
  36.  
  37. A word on the multi-tasking nature  of  Intuition  might  be
  38. helpful.  As far as your program is concerned, Intuition has
  39. "two parts" in that Intuition library code may be run on two
  40. schedules:  your program (assuming your program has a single
  41. task accessing Intuition) and the Input Device.  The  latter
  42. is  a  task that runs on the user-interaction schedule as an
  43. input handler (the entry point is called  Intuition()).   It
  44. appears  to  your  code  almost  as if it were running as an
  45. interrupt, since it runs  at  high  priority  and  thus  can
  46. preempt your task.
  47.  
  48. The synchronization of the input schedule and your  program,
  49. and  the  arbitration of data structures shared by your pro-
  50. gram and the Intuition input handler are the two most  deli-
  51. cate topics which are discussed below.
  52.  
  53.  
  54. 2.  SCREENS
  55.     =======
  56.  
  57. Height and Position
  58.      In support of PAL displays (which  support  more  lines
  59.      than  their  US  counterparts), a method is provided to
  60.      open screens to their full height on any display.  This
  61.      is  done by specifying the value STDSCREENHEIGHT in the
  62.      NewScreen.Height field (this  constant  is  defined  in
  63.      intuition.h).
  64.  
  65.      If you intend to provide your own CUSTOMBITMAP for  the
  66.      screen,  you  need  to  know how big the screen will be
  67.      before opening it.  This is done by examining the  pub-
  68.      lic  field  GfxBase->NormalDisplayRows.  Note that that
  69.      field  specifies  the  non-interlaced  count   (on   US
  70.      machines it is 200).
  71.  
  72.      A new feature: screens of less than full height are not
  73.      constrained to the bottom portion of the display.  When
  74.      opened, screens will appear  (safely)  at  the  display
  75.      position  specified in NewScreen.TopEdge.  The user can
  76.      drag short screens up to the top of the  display.   The
  77.      display  area  at  the  bottom of the display below the
  78.      bottom of a short screen is  solid  in  the  background
  79.      color of the front screen.
  80.  
  81.      At the bottom of the display, beyond NormalDisplayRows,
  82.      the  image of the frontmost screen is continued and may
  83.      be visible.  The mouse is constrained, however, so that
  84.      it  remains in the "working region" of the display View
  85.      structure, which extends only from the top of the  view
  86.      to NormalDisplayRows.
  87.  
  88. Workbench Screen Inquiry
  89.      Programs opening windows on the  Workbench  Screen  may
  90.      inquire  to find out its size, the size of its Menu bar
  91.      area, and so on, by using the function GetScreenData().
  92.      This function will open the Workbench screen if it hap-
  93.      pens to be closed.  Thus is best suited  to  use  by  a
  94.      program about to open a window on the Workbench screen.
  95.  
  96.      Workbench  Screen  Inquiry  also  applies   to   custom
  97.      screens, but the need for that will be rare.
  98.  
  99. New Flags for NewScreen
  100.      Some new features are provided and invoked  by  setting
  101.      new  flags  in the NewScreen.Flags field.  These values
  102.      are defined in intuition.h.
  103.  
  104.      SCREENBEHIND --  indicates  that  when  the  screen  is
  105.      opened,  it  should be behind all other screens.  Among
  106.      other uses, this method allows  a  program  to  prepare
  107.      imagery  in  the  screen, change its colors, and so on,
  108.      bringing it to the front when it becomes presentable.
  109.  
  110.      SCREENQUIET -- addresses the  problem  of  doing  fancy
  111.      viewport  operations  in  your custom screen.  A screen
  112.      opened with this flag will not have  a  title  bar  nor
  113.      visible  gadget  rendering,  but the dragging and depth
  114.      arrangement  facilities  provided  by  Intuition  still
  115.      function.   In  order  to  completely prevent Intuition
  116.      from rendering into your screen, you  must  also  catch
  117.      the  menu  button  in  each window in the screen, using
  118.      MENUVERIFY or RMBTRAP.
  119.  
  120. A Warning on Dual Playfields
  121.      Setting the DUALPF flag in the NewScreen.Flags field is
  122.      not  the  best  method  of  obtaining  a dual playfield
  123.      viewport for your screen.  It is better to open a stan-
  124.      dard screen, passing to Intuition (or letting Intuition
  125.      create) only one of your playfield bitmaps  (the  front
  126.      one).   Then  you  allocate and set up a second BitMap,
  127.      its bit-planes, and a RasInfo structure.  Install these
  128.      into  new  screen's viewport, change the viewport modes
  129.      to include DUALPF, MakeScreen(), and  RethinkDisplay().
  130.      An  example  appears at the end of this document.  This
  131.      method keeps Intuition rendering (gadgets, menus,  win-
  132.      dows) in a single playfield.
  133.  
  134.  
  135. 3.  WINDOWS
  136.     =======
  137.  
  138. ActivateWindow()
  139.      This function allows a  program  to  activate  windows,
  140.      hopefully  in  a  way that doesn't confuse or frustrate
  141.      the user.  An example of a system  program  using  this
  142.      function  on  a  (long,  narrow)  window along with the
  143.      related function ActivateGadget() (see  below)  is  the
  144.      Workbench Rename operation.
  145.  
  146.      See the autodocs for this function, as its use  is  not
  147.      entirely straightforward.
  148.  
  149. Window Borders
  150.      Window borders are no longer excessively updated when a
  151.      window  is  made active, the window's title is changed,
  152.      or the window is brought to the front.  Window  borders
  153.      are  refreshed,  when  necessary,  through the window's
  154.      layer's DamageList, which further minimized the  visual
  155.      activity    (essentially    under   the   auspices   of
  156.      Begin/EndRefresh()).
  157.  
  158.      A lot of  attention  has  gone  into  establishing  the
  159.      correct  damage  region for a smart refresh window.  It
  160.      is now possible for  application  programs  to  refresh
  161.      their  smart  windows  in  between  BeginRefresh()  and
  162.      EndRefresh() and get good results.  The  refreshing  of
  163.      gadgets  can be more complicated, and is covered below,
  164.      in Section 3, Gadgets.
  165.  
  166.      The drag gadget in the top border is rendered in a more
  167.      solid  pattern  which  appears more stable in an inter-
  168.      laced display.
  169.  
  170. Dimensions
  171.      The position/dimensions  of  windows  when  opened  now
  172.      undergo error checking.  The maximum dimensions (speci-
  173.      fied as NewWindow.MaxWidth/MaxHeight) are now  unsigned
  174.      quantities,  and  may  be  legally  set to a maximum by
  175.      using the value 0xFFFF, better expressed as (~0).
  176.  
  177. Refreshing
  178.      Be sure to use Begin/EndRefresh() as  directed  in  the
  179.      manual,    or    set    the   NOCAREREFRESH   flag   in
  180.      NewWindow.Flags.  When using  Begin/EndRefresh(),  res-
  181.      trict your operations to simple rendering.  Avoid calls
  182.      that may lock the  LayerInfo,  or  get  complicated  in
  183.      Intuition,  since  BeginRefresh()  leaves  the window's
  184.      Layer(s) locked.  All rendering functions of  Intuition
  185.      or  Graphics are OK.  RefreshGadgets() is OK, but prob-
  186.      ably unnecessary.  AutoRequest() is to be avoided,  and
  187.      therefore all disk related DOS calls.
  188.  
  189.      A new function, RefreshWindowFrame(),  is  provided  in
  190.      the  event  that  your program has been trashing window
  191.      borders and wants to clean up.
  192.  
  193. RMBTRAP
  194.      The RMBTRAP bit in Window.Flags may be modified on  the
  195.      fly  by your program.  To be entirely proper, it should
  196.      be set or cleared as an atomic operation, which can  be
  197.      done  in  assembler,  using  a hot compiler, or by sur-
  198.      rounding it with Forbid/Permit().
  199.  
  200.  
  201.  
  202. 4.  GADGETS
  203.     =======
  204.  
  205. 4.1  General
  206.  
  207. Gadget List Functions
  208.      The functions to add, remove, and  refresh  gadgets  in
  209.      windows  or  requesters:  (AddGadget(), RemoveGadget(),
  210.      and RefreshGadgets()) have  analogies  which  apply  to
  211.      lists of gadgets linked by the Gadget.NextGadget field.
  212.      Each   function   (AddGList(),    RemoveGList(),    and
  213.      RefreshGList())  takes a parameter determining how many
  214.      gadgets in a list are to be operated on.  In each case,
  215.      operation  terminates  if  a  NextGadget field contains
  216.      NULL; a parameter value of -1  means  that  the  entire
  217.      list (until NULL) is processed.
  218.  
  219.      The function NewModifyProp() has  the  same  parameter,
  220.      with  regard  to the old ModifyProp(). The new function
  221.      takes a gadget count parameter to allow  finer  control
  222.      of  the refreshing of gadgets.  See Section 3.2, Gadget
  223.      Rendering for the behavior of each of these.
  224.  
  225.      Also refer to the  autodocs  for  more  information  on
  226.      these gadget functions.
  227.  
  228. ActivateGadget()
  229.      A String (or Integer) Gadget may be  "activated"  under
  230.      program  control.  If successful, this function has the
  231.      same effect as the user clicking the SELECT button when
  232.      the  mouse  pointer is within the bounds of the gadget.
  233.      Subsequent keystrokes accomplish entry and  editing  on
  234.      the  gadget's  string.   This function will fail if the
  235.      window  or  requester  containing  the  gadget  is  not
  236.      active.  It will also fail if the user is in the middle
  237.      of some other interaction, such as menu or proportional
  238.      gadget  operation.   See  the  ActivateGadget() autodoc
  239.      section.
  240.  
  241. Custom Screen Gadgets
  242.      These gadgets have never been supported, and are not in
  243.      1.2.   The  commercial  version  of the manual reflects
  244.      this observation.
  245.  
  246. Gadget Flags
  247.      The TOPBORDER flag bit in Gadget.Activation can be  set
  248.      to   indicate  to  Intuition  that  a  gadget  must  be
  249.      refreshed after  Intuition  has  rendered  in  the  top
  250.      border area of a window.
  251.  
  252.      The REQGADGET flag (for Requester Gadgets) must reflect
  253.      the  truth.  As an assistance, Intuition sets or clears
  254.      this flag  appropriately  when  gadgets  are  added  or
  255.      windows/requesters are opened.
  256.  
  257.      The SELECTED flag is now set even  for  system  gadgets
  258.      when they are in use.  We don't advise you rely heavily
  259.      on such state flags of data  structures  that  are  not
  260.      assigned to your program.
  261.  
  262.  
  263. 4.2  Gadget Refreshing by Intuition
  264.  
  265. Gadgets are refreshed by Intuition whenever a  layer  opera-
  266. tion  has  damaged  the  layer of the window or requester to
  267. which  they  are  attached.   In  the  processing   of   the
  268. REFRESHWINDOW  message,  the  typical  program  needn't call
  269. RefreshGadgets() at all.
  270.  
  271. Intuition's refresh of the gadgets of  a  damaged  layer  is
  272. done  "Through  the  Layer's Damage List."   This means that
  273. rendering is clipped to the layer's Damage Region--the  part
  274. of  the window's layer which needs refreshing because it has
  275. been exposed by a layer operation.
  276.  
  277. To be  precise,  Intuition  calls  layers/BeginUpdate()  and
  278. EndUpdate()  (Intuition  user  (i.e.,  your) equivalents are
  279. Begin/EndRefresh()) so that rendering is restricted  to  the
  280. Region   Layer.DamageList   (see  Windows,  above,  and  the
  281. Begin/EndRefresh() function descriptions  in  the  Intuition
  282. manual, and layers/BeginUpdate in the autodocs).
  283.  
  284. Gadgets which are positioned (GRELBOTTOM GRELRIGHT) or sized
  285. (GRELWIDTH,  GRELHEIGHT) relative to the dimensions of their
  286. window pose a problem when the window is  sized,  since  the
  287. visuals  for  these  gadgets must change, and are not neces-
  288. sarily in the damage region.
  289.  
  290. Therefore, Intuition must add the original  and  new  visual
  291. regions  for  such  relative  gadgets  to  the Damage Region
  292. before it goes about refreshing gadget rendering.
  293.  
  294. Relative gadgets  that  have  Border,  Image,  or  Intuitext
  295. imagery  extending  beyond  their  respective  select  boxes
  296. should  be  refreshed   by   the   program   itself   (using
  297. RefreshGlist())  when receiving a Newsize event for the win-
  298. dow.  This gadget refreshing  should  not  be  done  between
  299. BeginRefreshing () and EndRefresh(), in order to present the
  300. visuals beyond the extent of the damage region.
  301.  
  302.  
  303. 4.3  Gadget Refreshing by Programs
  304.  
  305. If you add  gadgets  to  your  window  or  requester  (using
  306. AddGlist(),  or  AddGadgets())  you  must  subsequently call
  307. RefreshGList() or RefreshGadgets() to get the image of  your
  308. gadget drawn.
  309.  
  310. Several calls actually cause the refresh of  more  than  one
  311. gadget.  The behavior under v1.1 of these functions has been
  312. unchanged in  v1.2  This  was  not  true  for  several  beta
  313. releases.   In  each case, an alternative function or method
  314. is available for new programs to better control the refresh-
  315. ing  of  gadgets  so  that  only  modified  gadgets  need be
  316. redrawn.
  317.  
  318. The  functions  which   refresh   gadgets   in   v1.1   are:
  319. RefreshGadgets(), OnGadget(), OffGadget(), and ModifyProp().
  320. Their behavior and alternatives are described below:
  321.  
  322. RefreshGadgets()
  323.      In v1.1, this function is documented as refreshing  all
  324.      gadgets  from  the  one  whose  address  is passed as a
  325.      parameter  to  the  end  of   the   list   (linked   by
  326.      Gadget.NextGadget).   If applied to a requester gadget,
  327.      though, ALL gadgets  in  the  requester  were  redrawn.
  328.      This  is  the case in (the final releases of) v1.2, for
  329.      compatibility.
  330.  
  331.      The alternative is to use RefreshGList(), which takes a
  332.      parameter  to determine exactly which gadgets are to be
  333.      refreshed.
  334.  
  335. ModifyProp()
  336.      This function simply modifies some values in  the  Pro-
  337.      pInfo  structure  of  a  propotional  gadget  and calls
  338.      RefreshGadgets(), the excessive behavior  of  which  is
  339.      described above.
  340.  
  341.      The alternative is to call NewModifyProp().   This  new
  342.      function   takes   a   parameter   in   the  manner  of
  343.      RefreshGList()  to  control   the   gadget   refreshing
  344.      activity.
  345.  
  346. OnGadget() and OffGadget
  347.      These  functions  simply  clear  or  set  (resp.)   the
  348.      GADGDISABLED   flag   of  the  gadget,  and  then  call
  349.      RefreshGadgets().  There are no  alternative  functions
  350.      for  these, since they each can be implemented by manu-
  351.      ally  modifying  the  GADGDISABLED  flag  and   calling
  352.      RefreshGList(), as described below.
  353.  
  354. Some programs use RefreshGadgets() (better,  RefreshGList())
  355. to  update the display after they have made state changes to
  356. the gadgets.  The types of  changes  include:  the  SELECTED
  357. flag  for Boolean Gadgets to implement home-rolled MUTUALEX-
  358. CLUDE for Boolean Gadgets, the GadgetText of some gadget  to
  359. change its label, the GADGDISABLED flag, and the contents of
  360. StringInfo.Buffer of a String  Gadget.  (See  Section  3.6.1
  361. Mutual  Exclusion for an example.) On this subject, we offer
  362. the following:
  363.  
  364.      Be sure to RemoveGadget() any gadget before alter-
  365.      ing  it.  Understand that Boolean Gadgets rendered
  366.      with Borders (instead of  Images)  or  highlighted
  367.      with surrounding boxes (GADGHBOX) are handled very
  368.      simply by Intuition, and that complicated  transi-
  369.      tions  done by your program (and in some cases the
  370.      user's own actions) can get the rendering  out  of
  371.      phase.
  372.  
  373.  
  374. 4.4  String Gadgets
  375.  
  376. The most important change in string gadgets is  the  Activa-
  377. teGadget() function described under GADGETS.
  378.  
  379. When the user selects a string gadget with  the  mouse,  the
  380. gadget's cursor moves to the position of the mouse.
  381.  
  382. Several bugs have been fixed.  It is  now  possible  to  use
  383. RELWIDTH  string  gadgets.  Integer (LONGINT) string gadgets
  384. now have the LongInt value updated whenever the textual con-
  385. tents  of  the  gadget changes, and again, for good measure,
  386. when the gadget is de-activated.
  387.  
  388.  
  389. 4.5  Proportional Gadgets
  390.  
  391. There is a new function NewModifyProp() which is the same as
  392. ModifyProp() with additional control over gadget refreshing.
  393. See the sections above for details.
  394.  
  395. Highlighting by alternate knob  image  (GADGHIMAGE)  is  now
  396. supported,  but you should make the alternate image the same
  397. size as the normal knob image.
  398.  
  399. Proportional gadgets are often used for  scrolling  graphics
  400. or  textual information.  To do this in your program (assum-
  401. ing vertical scrolling), it  is  necessary  to  convert  the
  402. relationships  between  the  visible fraction of the display
  403. and the VertBody value, and the top line of the display  and
  404. the VertPot value.
  405.  
  406. Consider as an example scrolling a 25 line  view  of  a  100
  407. line    display.     In   the   following,   the   variables
  408. "visible_lines" and "total_lines" would take the  values  25
  409. and 100, respectively.
  410.  
  411. The first  relationship  is  simple:  make  the  Body  value
  412. represent "one-fourth." This can be expressed as
  413.  
  414.      VertBody = (ULONG)(visible_lines*0xFFFF)/total_lines;
  415.  
  416. If  you  are  hard-up  for  cycles  and   can   avoid   zero
  417. visible_lines, this seems to work nicely:
  418.  
  419.      VertBody = ((ULONG)(visible_lines<<16) -1)/total_lines;
  420.  
  421. Now, note that when you are displaying the last "page," line
  422. 75 is the top line in view (start line numbers from zero).
  423.  
  424. Therefore, when the VertPot value is a maximum (0xFFFF)  you
  425. need  to  convert  this  to 75, and so on.  This can be done
  426. like so:
  427.  
  428.      top_line = 
  429.     ((ULONG)(total_lines-visible_lines)*VertPot+(1<<15))>>16;
  430.  
  431. The inverse of this operation is needed if you wish to  ini-
  432. tialize the pot for some particular value of top_lines.
  433.  
  434.      VertPot = MIN(0xFFFF,
  435.          ((top_line_input<<16))/(total_lines-visible_lines));
  436.  
  437. The MIN macro is used because "unity" is actually 0xFFFF.
  438.  
  439.  
  440.  
  441. 4.6  Boolean Gadgets
  442.  
  443. Some minor bug fixing: Gadget Text may be used with  gadgets
  444. highlighted   by   Alternate   Image  display  (GADGHIMAGE).
  445. Selecting gadgets while other Intuition display activity  is
  446. going on no longer confuses the system.
  447.  
  448.  
  449. 4.6.1  Mutual Exclusion
  450.  
  451. Intuition managed Mutual Exclusion  of  Boolean  Gadgets  is
  452. still  not  provided;  rather, a flexible method of doing it
  453. yourself is recommended:
  454.  
  455.      Remove a Boolean gadget from the window or reques-
  456.      ter  it  is  attached to (RemoveGadget()).  Set or
  457.      clear the SELECTED flag to reflect  the  state  of
  458.      the  gadget  you  desire  to  display to the user.
  459.      Replace the gadget (AddGadget()) and  refresh  its
  460.      imagery (RefreshGList()).
  461.  
  462. More than one gadget can be  processed  using  RemoveGList()
  463. and  AddGList(),  with  a  single  call to RefreshGList when
  464. done.
  465.  
  466. It is strongly recommended that you play  these  games  only
  467. with Boolean gadgets rendered with images and highlighted by
  468. complement mode rendering.   Further,  the  Activation  Type
  469. should   be  GADGIMMEDIATE  (and  not  RELVERIFY,  nor  TOG-
  470. GLESELECT) with your state changes executed  upon  receiving
  471. the GADGETDOWN message.
  472.  
  473.  
  474. 4.6.2  Masked Gadgets
  475.  
  476. A new feature allows non-rectangular Boolean  gadgets,  with
  477. some restrictions.  An auxilliary bit plane called a Mask is
  478. associated with a gadget.  When the user selects within  the
  479. select  box  of the gadget, a further test is made to see if
  480. the selection point is contained in the mask.   Only  if  so
  481. does the interaction count as a gadget "hit".
  482.  
  483. If the gadget has highlight type  GADGHCOMP  the  complement
  484. rendering is restricted to the mask, which allows, for exam-
  485. ple, an oval gadget which highlights nicely, only within the
  486. oval.
  487.  
  488. However, there are some shortcomings.  The gadget  image  is
  489. not  rendered through the mask.  For example, in the case of
  490. an oval mask the image is still a rectangle, and when it  is
  491. displayed, it will clobber the corner areas even though they
  492. are outside of the oval.  This means they can't  be  crowded
  493. together without care.
  494.  
  495. Likewise, the ghosting of a disabled gadget does not respect
  496. the  mask,  so ghosting of the corners around an oval may be
  497. visible, depending on the colors involved.
  498.  
  499. An example appears at the end of this note.
  500.  
  501.  
  502. 5.  MENUS
  503.     =====
  504.  
  505. 5.1  Flags
  506.  
  507. MENUTOGGLE
  508.      This flag can be set by your program, and  now  behaves
  509.      as  the  Intuition manual describes.  The author apolo-
  510.      gizes for not finding the bug in time to get this  into
  511.      1.1.   Set  this flag for a CHECKIT menu (sub-)item and
  512.      the item can be selected to turn the checkmark off,  as
  513.      well as on.
  514.  
  515. MENUSTATE
  516.      This flag is set in Window.Flags when the menus of that
  517.      window are in use. Beware: in typical event-driven pro-
  518.      gramming, such a state variable  is  not  on  the  same
  519.      time-table  as  your input message handling, and should
  520.      not be used to draw profound conclusions in  your  pro-
  521.      gram.   It  is  better to synchronize yourself with the
  522.      menu handling using MENUVERIFY.
  523.  
  524. 5.2  Shortcuts and MENUVERIFY
  525.  
  526. The idea behind MENUVERIFY (and to  some  degree  SIZEVERIFY
  527. and   REQVERIFY)   is   to  synchronize  your  program  with
  528. Intuition's menu handling sessions.  The  motivating  reason
  529. was  to  allow  your  program  to  arbitrate  access to your
  530. screen's bitmap, so that Intuition doesn't put menus in  the
  531. way  of your drawing.  This circumstance is obviated to some
  532. extent by the fact that Intuition will lock all layers on  a
  533. screen before any menus are displayed, and if your rendering
  534. is solely through windows you will be  automatically  locked
  535. out until menus are done.
  536.  
  537. Some programs use MENUVERIFY to permit them to intercept the
  538. right  mouse  button,  thereby  to use it for their own pur-
  539. poses.  Other programs use  MENUVERIFY  to  briefly  suspend
  540. menu  operations  while  they  restore Wild Phenomena before
  541. menu operations proceed.  These phenomena may  be  illegible
  542. colors  of  the  screen  or  double  buffering  and  related
  543. ViewPort operations.
  544.  
  545. In any case, it is vital to know when menu  operations  ter-
  546. minate.   This  is  typically  detected  by watching for the
  547. MENUPICK IDCMP message.  If you intercepted (MENUCANCEL) the
  548. menu  operations, you will instead receive MOUSEBUTTONS mes-
  549. sage with code equal to MENUUP.  Menu  shortcut  keystrokes,
  550. for compatibility, also respect MENUVERIFY.  They are always
  551. paired with a MENUPICK message (unlike v1.1)  so  that  your
  552. program knows the menu operation is over.
  553.  
  554. Use of MENUVERIFY was recommended only with a healthy set of
  555. caveats,  and with a publically available program you needed
  556. named KillVerify(), simply because there  was  no  deadlock-
  557. safe   way   to  turn  MENUVERIFY  off.  Now  you  may  call
  558. ModifyIDCMP() with confidence to  turn  MENUVERIFY  and  the
  559. other VERIFY IDCMP options off.  It is important that you do
  560. so if you ever do anything that directly or  indirectly  has
  561. you  waiting  for  Intuition (since Intuition may be waiting
  562. for you).
  563.  
  564. Intuition now handles its internal functions  automatically,
  565. so  you can safely open and close windows, change your menus
  566. (Clear/SetMenuStrip), and play with your gadgets.  You  can-
  567. not,  however,  wait  for  a  gadget  or mouse event without
  568. checking also for any MENUVERIFY  event  messages  that  may
  569. require your response.
  570.  
  571. The most common problem area is  Sytem  Requesters  (AutoRe-
  572. quest()).  Before AutoRequest() returns control to your pro-
  573. gram, Intuition must be free to run and  accept  a  response
  574. from  the user.  If the user presses the menu button, Intui-
  575. tion will  wait  for  you  to  MENUVERIFY  and  there  is  a
  576. deadlock.
  577.  
  578.      THERFORE: USE THE FUNCTION ModifyIDCMP()  TO  TURN
  579.      OFF  ALL  VERIFY  MESSAGES BEFORE YOU CALL AutoRe-
  580.      quest() OR THE DOS (!!!) SINCE MANY  ERROR  CONDI-
  581.      TIONS IN THE DOS REQUIRE USER INPUT IN THE FORM OF
  582.      AUTOREQUESTS.
  583.  
  584.  
  585. 5.3  Miscellaneous
  586.  
  587. Highlighting
  588.      Item  and  SubItem  highlighting  by  Alternative  Text
  589.      display now works.  The item must be a text item (ITEM-
  590.      TEXT) and the highlighting flag is  set  to  HIGHIMAGE.
  591.      MenuItem.SelectRender  must,  of  course,  point  to an
  592.      IntuiText structure.
  593.  
  594. Menu shortcut keys 'M' and 'N' now work.
  595.  
  596. Try not to leave space between the select boxes of your menu
  597. items  and  (especially)  your  subitems.   When the pointer
  598. moves off of one subitem into the gap  between  it  and  the
  599. next  subitem,  the  entire  submenu  is erased and redrawn,
  600. which doesn't look real sharp.
  601.  
  602.  
  603.  
  604. 6.  REQUESTERS
  605.     ==========
  606.  
  607. Pointer Relative Requesters
  608.      By setting  the  POINTREL  Flag  in  a  Requester,  and
  609.      installing  the  requester  as  a Double Menu Requester
  610.      (Set/ClearDMRequest()), you get a requester that  comes
  611.      up  under the mouse pointer when the user double clicks
  612.      the right mouse button.
  613.  
  614.      The values of the fields  Requester.RelLeft/Top  deter-
  615.      mine  the  point on the requester the the mouse will be
  616.      over (experiment).  The requester position will be res-
  617.      tricted  in  an  attempt  to  make  it entirely visible
  618.      (i.e., contained in its window).
  619.  
  620. Noisy Requesters
  621.      You may set the NOISYREQ flag if you do  not  want  the
  622.      presence  of  a  Requester to inhibit your normal input
  623.      flow.  Gadgets and menus will remain activated, but you
  624.      will  be able to hear the keyboard and the mouse.  This
  625.      technique is  used  in  the  new  keyboard  feature  of
  626.      AutoRequest() (see below).
  627.  
  628. FlagsThe REQACTIVE flag  bit  (in  Requester.Flags)  is  now
  629.      always  set  and  cleared as your requesters are posted
  630.      and removed.  The  active  requester  has  always  been
  631.      indicated by the value of Window.FirstRequest.
  632.  
  633. System Requests (AutoRequest())
  634.      By using the new NOISYREQ Requester Flag, AutoRequest()
  635.      now  allows  the  user to satisfy a system request from
  636.      the keyboard.  The key strokes left-Amiga-V  and  left-
  637.      Amiga-B correspond to the left and right system request
  638.      gadgets, respectively.
  639.  
  640.      When a System Request is posted (using AutoRequest() or
  641.      BuildSysRequest())  it  will move the screen it appears
  642.      in to the front (if it is not  already  the  foremost).
  643.      This  change was made after too many users were reboot-
  644.      ing their  machines  when  programs  that  used  custom
  645.      screens  appeared  to "lock-up" - due to the notice DOS
  646.      put up on the workbench screen.  Now these  users  need
  647.      to  learn  to  re-arrange  the  screens after they have
  648.      satisfied a Request which has  pre-empted  their  work,
  649.      since the screens are not re-arranged to their original
  650.      state.
  651.  
  652. User Rendering
  653.      A Requester appears in a Layer.  You may render to this
  654.      layer  through  its  RastPort,  which  can  be found as
  655.      Requester.ReqLayer.rp.  The Requester layer  is  smart,
  656.      so  that your rendering is preserved, but it the window
  657.      is sized it may damage your work, so that you will need
  658.      to refresh your rendering.
  659.  
  660. IDCMP Changes
  661.      The REQSET and REQCLEAR messages are now sent for  each
  662.      Requester  that is put up or removed (resp.) instead of
  663.      only for the first and last (resp.).  This change  pro-
  664.      vides more information for those programs trying to use
  665.      more than one requester, especially if  they  are  also
  666.      trying to be tricky with ActivateGadget().
  667.  
  668.  
  669. 7.  ALERTS
  670.     ======
  671.  
  672. If a recoverable Alert cannot be displayed (because of  low-
  673. memory),  DisplayAlert()  will  return FALSE, as if the user
  674. had selected CANCEL.  Formerly, the Alert would be converted
  675. into a dead-end alert (Guru Meditation) claiming that Intui-
  676. tion was in a panic, and that just didn't seem  fair.   Note
  677. that  a  System  Request  (AutoRequest()  or  BuildSystemRe-
  678. quest()) will convert into  a  recoverable  alert,  so  this
  679. change  means  that numerous errors in low memory conditions
  680. which appeared to crash the machine won't  be  doing  so  in
  681. 1.2.
  682.  
  683. The part of the recoverable alert message which says  "RIGHT
  684. BUTTON CANCEL" is displayed in 1.2, fix of a bug in 1.1.
  685.  
  686.  
  687. 8. LOCKING and RE-ENTRANCY
  688.    =======================
  689.  
  690. General Locking
  691.      The multi-tasking access of Intuition  data  structures
  692.      is  now  arbitrated by the use of Exec SignalSemaphores
  693.      (see the autodocs).  This should  eliminate  incidences
  694.      of clashing use of windows, Intuition linked lists, the
  695.      dreaded busyWaitForbid(),  Screen  RastPort  confusion,
  696.      and  the  like.   In  the  alpha and beta stages, these
  697.      problems were all replaced with  system  deadlocks,  at
  698.      one time or another, and finally were all eliminated in
  699.      the final versions.
  700.  
  701.      The  application  programmer's  exposure  to  Intuition
  702.      locking  is  minimized.   A  pair of entry points named
  703.      LockIBase() and  UnlockIBase()  are  provided  to  gain
  704.      access to locks which assure the integrity of the state
  705.      of IntuitionBase (the  intuition.library  static  data)
  706.      and  of  the  linked lists of Screens and Windows.  The
  707.      autodoc sections for these functions explains in  great
  708.      detail  the  intended  use  and  cautions pertaining to
  709.      these functions.  In particular, be VERY  careful  that
  710.      you  pass the parameters described, or you may be open-
  711.      ing vulnerabilities in the system that will not  appear
  712.      as   problems  until  your  program  is  running  in  a
  713.      heavily-laden multi-tasking environment.
  714.  
  715.      The author-programmer makes  this  request:  don't  get
  716.      tricky with these locks.
  717.  
  718. Intuition's Use of Your RastPort
  719.  
  720.      Intuition has many rendering chores:
  721.      screen and window titles and borders,  gadgets,  menus,
  722.      and  so  on.  In v1.2, Intuition will use a copy of the
  723.      RastPort of the screen in which  the  rendering  is  to
  724.      take  place.   This copy will determine the bitmaps the
  725.      rendering will end up in, and often the font and  simi-
  726.      lar modal information.
  727.  
  728.      One thing Intuition sets each time is the mask value of
  729.      the  RastPort.  It is set to all ones (0xFFFF).  If you
  730.      wish to restrict Intuition's rendering to all bitplanes
  731.      of  your  screen,  you  may change the Depth and Planes
  732.      values  in  Screen.RastPort.BitMap.   This  will   only
  733.      effect rendering into the screen itself, which consists
  734.      of the Screen title and  gadgets,  and  menus.   Window
  735.      gadgets  are not fooled, since they use the mask in the
  736.      window's layer's rastport,  which  you  should  not  be
  737.      changing.
  738.  
  739.  
  740.  
  741. 9. IDCMP and INPUT EVENTS
  742.    ======================
  743.  
  744. Keyboard Messages
  745.      VANILLAKEY IDCMP Class (which does not  appear  in  the
  746.      original  version  of the manual) has not been enhanced
  747.      from 1.1, for compatibility.  It provides a translation
  748.      from  RAWKEY  input event using the system default key-
  749.      map, but only sends an IDCMP message if the translation
  750.      results  in  a single byte (which is passed in the Code
  751.      field of the VANILLAKEY IDCMP message).
  752.  
  753.      Most programs will  prefer  to  use  the  RAWKEY  IDCMP
  754.      class, and perform their own RawKeyConvert().  See also
  755.      DeadKeyConvert(), below.
  756.  
  757. Dead Keys
  758.      The  IntuiMessages  are  converted  from   InputEvents.
  759.      InputEvents  now  (in v1.2) contain information for the
  760.      processing of so-called Dead Keys, which  refers  to  a
  761.      technique   of   generating  a  diacritical  using  two
  762.      separate keystrokes.  (See release notes  on  keymaps.)
  763.      This  information is passed in RAWKEY IDCMP messages in
  764.      a location  pointed  to  by  the  IntuiMessage.IAddress
  765.      field.   The  following  example  shows how to use this
  766.      information and the ConsoleDevice  function  RawKeyCon-
  767.      vert()   to  convert  RAWKEY  messages  into  character
  768.      values.
  769.  
  770.     /* must have the ConsoleDevice opened to use RawKeyConvert() */
  771.     struct Device *ConsoleDevice;       /* external declaration */
  772.     struct IOStdReq ioreq;
  773.         ...
  774.     OpenDevice("console.device", -1, &ioreq, 0);
  775.     ConsoleDevice = ioreq.io_Device;
  776.         ...
  777.  
  778.     /* DeadKeyConvert()
  779.      * returns:
  780.      *  -2 if msg is not class RAWKEY
  781.      *  same as RawKeyConvert otherwise:
  782.      *  buffer length if <= kbsize
  783.      *  -1 else
  784.      */
  785.     DeadKeyConvert(msg, kbuffer, kbsize, kmap)
  786.     struct IntuiMessage *msg;
  787.     UBYTE *kbuffer;
  788.     int kbsize;
  789.     struct KeyMap *kmap;
  790.     {
  791.         static struct InputEvent ievent = {NULL, IECLASS_RAWKEY, 0, 0, 0};
  792.  
  793.         if (msg->Class != RAWKEY) return (-2);
  794.  
  795.         /* pack input event */
  796.         ievent.ie_Code = msg->Code;
  797.         ievent.ie_Qualifier = msg->Qualifier;
  798.  
  799.         /* get previous codes from location pointed to by IAddress
  800.          *  this pointer is valid until IntuiMessage is replied.
  801.          */
  802.          ievent.ie_position.ie_addr = *((APTR *)msg->IAddress);
  803.  
  804.         return ( RawKeyConvert(&ievent, kbuffer, kbsize, kmap) );
  805.     }
  806.  
  807.  
  808. Verify Messages
  809.      See the discussion in Section 4, Menus on the  MENUVER-
  810.      IFY IDCMP Flag.  All of that information applies to the
  811.      two other verify messages: REQVERIFY and SIZEVERIFY.  A
  812.      special  note:  a  bug  somewhere in the input handling
  813.      stream through Intuition may confuse window  sizing  by
  814.      the user if your program takes too much time responding
  815.      to the SIZEVERIFY message.  Please be quick.
  816.  
  817. MOUSEMOVE
  818.      Your program will not be sent MOUSEMOVE messages  while
  819.      Intuition  has the layers of your screen locked (during
  820.      menu  operations  and  window  sizing/dragging).   This
  821.      avoids  problems  of  messages  accumulating while your
  822.      program is blocked trying to render to  a  layer  which
  823.      Intuition has locked.
  824.  
  825. Bug Fixes
  826.      DELTAMOVE messages work.  Be advised that if  you  have
  827.      the  DELTAMOVE  IDCMP  flag set, your MOUSEBUTTONS mes-
  828.      sages will also have relative values,  instead  of  the
  829.      absolute window position of the mouse.
  830.  
  831.      NEWPREFS messages are sent if the NEWPREFS  IDCMP  flag
  832.      is set.  Sending it used to be determined by some other
  833.      flag values, by coincidence.
  834.  
  835.      Duplicate mouse messages for users of  RMBTRAP  are  no
  836.      longer sent.
  837.  
  838.      The INTUITICKS messages are paced: until you  reply  to
  839.      one,  no  subsequent one will be sent to you.  This was
  840.      not true in v1.1, but is fixed in 1.2.   This  has  the
  841.      effect  of making the messages appear to arrive half as
  842.      often, so programs using INTUITICKS to drive animations
  843.      appear to run slower.
  844.  
  845.      A NEWSIZE message will be sent when sizing  are  opera-
  846.      tions completed, even if the size of the window did not
  847.      actually change.  This is the way of 1.1, but was miss-
  848.      ing from some of the development releases of v1.2.
  849.  
  850.  
  851. 10.  MISCELLANEOUS
  852.      =============
  853.  
  854. Pointer Position Error
  855.      There was  a  bug  in  v1.1  graphics/MoveSprite()  and
  856.      resultingly in intuition/SetPointer().  For compatibil-
  857.      ity, we are forced to leave it in.   The  error  is  in
  858.      Sprite  positioning.   To  compensate  for it, you must
  859.      tell Intuition that the "hot spot" of a pointer  sprite
  860.      is  one  pixel  to  the  left  of the position actually
  861.      intended.  The Preferences  pointer  editor  adds  this
  862.      fudge  factor; only changes to the pointer done by your
  863.      program must compensate for this error.
  864.  
  865. Input Event Food Chain
  866.      The Intuition input  handler  now  no  longer  discards
  867.      linked  lists of input events longer than 10 in length,
  868.      and can handle linked lists of input events  in  string
  869.      gadgets.   This is only important to programs which add
  870.      input events to the Input Device  stream  either  using
  871.      their  own  handler or by using the IND_WRITEEVENT com-
  872.      mand of the Input Device (see the documentation on  the
  873.      Input Device).
  874.  
  875. Absolute Mouse Position
  876.      Intuition now handles pointer  position  input  events.
  877.      The input event class IECLASS_POINTERPOS can be used to
  878.      specify a position for the mouse  pointer  RELATIVE  TO
  879.      THE  INTUITION  VIEW  ORIGIN.  The coordinates are pro-
  880.      vided in the pseudo-fields ie_X  and  ie_Y  (these  are
  881.      really  part  of  a union).  Internally, Intuition will
  882.      convert this event  into  the  proper  RAWMOUSE  event,
  883.      replacing ie_X/Y with a suitable relative mouse motion.
  884.  
  885.      Note   that   the    presence    of    the    qualifier
  886.      IEQUALIFIER_RELATIVEMOUSE     indicates     that     an
  887.      IECLASS_POINTERPOS input  event  specifies  a  relative
  888.      mouse move, having the same effect as IECLASS_RAWMOUSE.
  889.  
  890. Public IntuitionBase
  891.      The include file intuition/intuitionbase.h  contains  a
  892.      definition  of the entire Intuition library data struc-
  893.      ture.  It also contains  very  important  warnings  and
  894.      specification  of  what  part  of  this  READ-ONLY data
  895.      structure may be used in a supported way, and  explains
  896.      the role of the functions LockIBase() and UnlockIBase()
  897.      in accessing the data it contains.
  898.  
  899. InstallClipRegion Support
  900.      This new function in layers.library allows specifying a
  901.      region  within  a window to which rendering is clipped.
  902.      Intuition needs to modify and restore this  information
  903.      to  perform its gadget rendering and border refreshing,
  904.      and does so in such a way as to be transparent to  your
  905.      program, in simple circumstances.
  906.  
  907. ReportMouse()
  908.      This function had a problem in  v1.1  that  caused  its
  909.      parameters  to  be  be handled in the order opposite of
  910.      that described in the  Intuition  manual.  For  a  full
  911.      explanation  of the current state of this function, and
  912.      an interesting lesson in software maintenance, see  the
  913.      autodoc section for this function.
  914.  
  915. PrintIText()
  916.      This function now safely handles the case of the actual
  917.      text  pointer-- IntuiText.IText--being NULL.  This rou-
  918.      tine is used internally for all Intuition rendering  of
  919.      IntuiText structures in menus and gadgets.
  920.  
  921. MemoryMenu operations (to name one thing) handle  low-memory
  922.      conditions better than in v1.1.  Specifically, menu and
  923.      submenu pages will not be  rendered  when  insufficient
  924.      memory exists for the internal auxilliary bitmaps.
  925.  
  926. DisplayBeep()
  927.      This function was not re-entrant  in  v1.1,  and  could
  928.      leave the screen in a "highlighted" state.  No more.
  929.  
  930. Mouse X and Y
  931.      These fields in Screens and Windows  are  now  properly
  932.      initialized when a screen or window is opened.
  933.  
  934. FontsIntuition now closes the  fonts  it  opens.   The  font
  935.      opened  when  a  window is opened is stashed in the new
  936.      Window field Window.IFont.  Intuition will  close  this
  937.      font  when the window is closed, and won't try to close
  938.      any font you have set in your window's  rastport.   You
  939.      must close such fonts yourself.
  940.  
  941.  
  942. 11.  DUAL-PLAYFIELD SCREEN EXAMPLE
  943.      =============================
  944.  
  945. /**************************************************************************
  946.  * Example program for Dual-Playfield Screens
  947.  *
  948.  * copyright Commodore-Amiga, Inc., Sept. 1986.  use at will
  949.  * author: jim mackraz (amiga!jimm)
  950.  *
  951.  * (Note - Attached code is Jim's updated example  c.s.)
  952.  ***************************************************************************/
  953.  
  954. /** wbdualpf.c :ts=8 **/
  955. /* Turn the workbench into dual playfield.
  956.  *
  957.  * You can use the same trick for your own screens,
  958.  * which is the recommended method for creating dual-playfield
  959.  * screens.
  960.  *
  961.  * -Start with a new, single-playfield screen
  962.  *  (don't set DUALPF in NewScreen.ViewModes)
  963.  * -Allocate a second playfield, set up a rastport for
  964.  *  rendering into it, and install it into your open screen
  965.  *  as shown here.  Intuition will never know about or use your
  966.  *  second playfield for its rendering (menus, gadgets, etc.).
  967.  * -Be sure to remove evidence of your deed before CloseScreen().
  968.  */
  969.  
  970. #include <exec/types.h>
  971. #include <exec/memory.h>
  972. #include <intuition/intuition.h>
  973.  
  974. #include <functions.h>
  975.  
  976. #ifdef ORIGINALCODE
  977. #define printf  kprintf
  978. #endif
  979.  
  980. struct  Remember    *rememberkey = NULL;
  981. struct  Window      *getNewWind();
  982.  
  983. struct  IntuitionBase   *IntuitionBase;
  984. struct  GfxBase         *GfxBase;
  985.  
  986. ULONG   flg = ACTIVATE | WINDOWCLOSE | NOCAREREFRESH | WINDOWDRAG
  987.         | WINDOWDEPTH | SIMPLE_REFRESH;
  988.  
  989. ULONG   iflg = CLOSEWINDOW | INTUITICKS ;
  990.  
  991. #define FANCYVERSION 1
  992. #if FANCYVERSION
  993. #define VISUALTICKS    30    /* intuiticks per frame    */
  994. #define CYCLETICKS    3    /* intuiticks per pen color    */
  995. #endif
  996.  
  997. main()
  998. {
  999.     struct  IntuiMessage    *msg;
  1000.     struct Window   *window = NULL;
  1001.     WORD    exitval = 0;
  1002.  
  1003.     /* hold data from *msg  */
  1004.     ULONG   class;
  1005.  
  1006.     /* specific for this test    */
  1007.     struct Screen *wbscreen;
  1008.     struct RasInfo *rinfo2 = NULL;    /* second playfield rasinfo ... */
  1009.     struct BitMap  *bmap2 = NULL;    /* ... and bitmap        */
  1010.     struct RastPort *rport2 = NULL;    /* for rendering into bmap2    */
  1011.     int       it_is_done = 0;        /* success flag            */
  1012.     int       counter = 0;            /* for timing the visuals    */
  1013.  
  1014.     if (!(IntuitionBase = (struct IntuitionBase *)
  1015.     OpenLibrary("intuition.library", 0L)))
  1016.     {
  1017.     printf("NO INTUITION LIBRARY\n");
  1018.     exitval = 1;
  1019.     goto EXITING;
  1020.     }
  1021.  
  1022.     if (!(GfxBase = (struct GfxBase *)
  1023.     OpenLibrary("graphics.library", 0L)))
  1024.     {
  1025.     printf("NO GRAPHICS LIBRARY\n");
  1026.     exitval = 2;
  1027.     goto EXITING;
  1028.     }
  1029.  
  1030.     /* get a window on the workbench    */
  1031.     window = getNewWind(320, 20, 300, 50, flg, iflg);
  1032.     if (window == NULL)
  1033.     {
  1034.     printf("test: can't get window.\n");
  1035.     exitval = 1;
  1036.     goto EXITING;
  1037.     }
  1038.  
  1039.  
  1040.     /* ------ Add a second playfield for Workbench ------------ */
  1041.  
  1042.     wbscreen = window->WScreen;        /* find it    */
  1043.  
  1044.     /* allocate second playfield's rasinfo, bitmap, and bitplane    */
  1045.  
  1046.     if (!(rinfo2 = (struct RasInfo *)
  1047.     AllocMem((LONG) sizeof(struct RasInfo), (LONG) MEMF_PUBLIC|MEMF_CLEAR)))
  1048.     {
  1049.     printf("alloc rasinfo failed\n");
  1050.     goto EXITING;
  1051.     }
  1052.  
  1053.     if (!(bmap2 = (struct BitMap *)
  1054.     AllocMem((LONG) sizeof(struct BitMap), (LONG) MEMF_PUBLIC|MEMF_CLEAR)))
  1055.     {
  1056.     printf("alloc bitmap failed\n");
  1057.     goto EXITING;
  1058.     }
  1059.  
  1060.     InitBitMap(bmap2, 1L, (LONG) wbscreen->Width, (LONG) wbscreen->Height);
  1061.  
  1062.     /* we'll use 1 plane. */
  1063.     if (!(bmap2->Planes[0] =
  1064.     (UBYTE *) AllocRaster((LONG) wbscreen->Width, (LONG) wbscreen->Height)))
  1065.     {
  1066.     printf("alloc raster failed\n");
  1067.     goto EXITING;
  1068.     }
  1069.  
  1070.     /* get a rastport, and set it up for rendering into bmap2    */
  1071.     if (!(rport2 = (struct RastPort *)
  1072.     AllocMem((LONG) sizeof (struct RastPort), (LONG) MEMF_PUBLIC)))
  1073.     {
  1074.     printf("alloc rastport failed\n");
  1075.     goto EXITING;
  1076.     }
  1077.     InitRastPort(rport2);
  1078.     rport2->BitMap = bmap2;
  1079.  
  1080.     SetRast(rport2, 0L);
  1081.  
  1082.     /* manhandle viewport: install second playfield and change modes    */
  1083.     Forbid();
  1084.  
  1085.     rinfo2->BitMap = bmap2;    /* install my bitmap in my rasinfo    */
  1086.  
  1087.     wbscreen->ViewPort.RasInfo->Next = rinfo2;
  1088.         /* install rinfo for viewport's second playfield    */
  1089.  
  1090.     wbscreen->ViewPort.Modes |= DUALPF;
  1091.                 /* convert viewport            */
  1092.     it_is_done = 1;
  1093.  
  1094.     Permit();
  1095.  
  1096.     /* set my foreground color */
  1097.     SetRGB4(&wbscreen->ViewPort, 9L, 0L, (LONG) 0xF, 0L);
  1098.     /* color 9 is color 1 for second playfield of hi-res viewport */
  1099.  
  1100.     /* put viewport changed into effect    */
  1101.     MakeScreen(wbscreen);
  1102.     RethinkDisplay();
  1103.  
  1104.     drawSomething(rport2);
  1105.  
  1106.     FOREVER
  1107.     {
  1108.     if ((msg = (struct IntuiMessage *)GetMsg(window->UserPort)) == NULL)
  1109.     {
  1110.         Wait((ULONG) 1<<window->UserPort->mp_SigBit);
  1111.         continue;
  1112.     }
  1113.  
  1114.     class   = msg->Class;
  1115.     ReplyMsg(msg);
  1116.  
  1117.     switch (class)
  1118.     {
  1119.     case INTUITICKS:
  1120. #if FANCYVERSION
  1121.         setPrimary(&wbscreen->ViewPort);    /* cycles colors */
  1122.         if (counter++ > VISUALTICKS)
  1123.         {
  1124.         counter = 0;
  1125.         SetRast(rport2, 0L);
  1126.         drawSomething(rport2);
  1127.         }
  1128. #endif
  1129.         break;
  1130.  
  1131.     case CLOSEWINDOW:
  1132.         goto EXITING;
  1133.     default:
  1134.         printf("unknown event: class %lx\n", class);
  1135.     }
  1136.     }
  1137.  
  1138. EXITING:
  1139.     /* clean up dual-playfield trick    */
  1140.     if (it_is_done)
  1141.     {
  1142.     Forbid();
  1143.     wbscreen->ViewPort.RasInfo->Next = NULL;
  1144.     wbscreen->ViewPort.Modes &= ~DUALPF;
  1145.     Permit();
  1146.     MakeScreen(wbscreen);
  1147.     RethinkDisplay();
  1148.     }
  1149.  
  1150.     if (rport2) FreeMem(rport2, (LONG) sizeof (struct RastPort));
  1151.     if (bmap2) 
  1152.     {
  1153.     if (bmap2->Planes[0])
  1154.     {
  1155.         FreeRaster(bmap2->Planes[0],
  1156.             (LONG) wbscreen->Width, (LONG) wbscreen->Height);
  1157.     }
  1158.     FreeMem(bmap2, (LONG) sizeof (struct BitMap));
  1159.     }
  1160.     if (rinfo2) FreeMem(rinfo2, (LONG) sizeof (struct RasInfo));
  1161.  
  1162.     if (window) CloseWindow(window);
  1163.     if (GfxBase) CloseLibrary(GfxBase);
  1164.     if (IntuitionBase) CloseLibrary(IntuitionBase);
  1165.  
  1166.     exit (exitval);
  1167. }
  1168.  
  1169. #if FANCYVERSION
  1170. /* cycle pen 1's color */
  1171. setPrimary(vp)
  1172. struct ViewPort *vp;
  1173. {
  1174.     static int current = 0;
  1175.  
  1176.     /* pen 1 is color 9 for second playfield in hires */
  1177.     /* feel free too do this elegantly */
  1178.  
  1179.     if (!(current++ % CYCLETICKS)) return;
  1180.  
  1181.     switch ((current/CYCLETICKS)%3)
  1182.     {
  1183.     case 0:
  1184.     SetRGB4(vp, 9L, 0xFL, 0L, 0L);
  1185.     break;
  1186.     case 1:
  1187.     SetRGB4(vp, 9L, 0L, 0xFL, 0L);
  1188.     break;
  1189.     case 2:
  1190.     SetRGB4(vp, 9L, 0L, 0L, 0xFL);
  1191.     break;
  1192.     }
  1193. }
  1194.  
  1195. struct pt_st {
  1196.     ULONG x;
  1197.     ULONG y;
  1198.     };
  1199.  
  1200. typedef struct pt_st Pt;
  1201.  
  1202. drawSomething(rp)
  1203. struct RastPort *rp;
  1204. {
  1205.     int width, height;
  1206.     LONG   RangeRand();
  1207.     int i;
  1208.  
  1209.     Pt start, vertex, end;    /* random reference lines */
  1210.     Pt p0, p1;        /* endpoints to be drawn    */
  1211.  
  1212.     width = rp->BitMap->BytesPerRow * 8;
  1213.     height = rp->BitMap->Rows;
  1214.  
  1215.     /* set up two random reference lines */
  1216.     start.x = RangeRand((LONG) width);
  1217.     vertex.x   = RangeRand((LONG) width);
  1218.     end.x   = RangeRand((LONG) width);
  1219.  
  1220.     start.y = RangeRand((LONG) height);
  1221.     vertex.y = RangeRand((LONG) height);
  1222.     end.y   = RangeRand((LONG) height);
  1223.  
  1224.     SetAPen(rp, 1L);
  1225.  
  1226.     /* draw lines connecting intermediate points */
  1227.     for (i = 0; i <= 0x100; i += 0x10)
  1228.     {
  1229.     /* point between start and vertex */
  1230.     p0.x = (start.x * (0xFF - i) + vertex.x  * i) >> 8;
  1231.     p0.y = (start.y * (0xFF - i)  + vertex.y * i) >> 8;
  1232.  
  1233.     /* point between vertex and end    */
  1234.     p1.x = (vertex.x * (0xFF - i) + end.x * i) >> 8;
  1235.     p1.y = (vertex.y * (0xFF - i) + end.y * i) >> 8;
  1236.  
  1237.     Move(rp, p0.x, p0.y);
  1238.     Draw(rp, p1.x, p1.y);
  1239.     }
  1240.  
  1241. }
  1242.  
  1243. #else
  1244.  
  1245. drawSomething(rp)
  1246. struct RastPort *rp;
  1247. {
  1248.     int width, height;
  1249.     int r, c;
  1250.  
  1251.     width = rp->BitMap->BytesPerRow * 8;
  1252.     height = rp->BitMap->Rows;
  1253.  
  1254.     SetAPen(rp, 1L);
  1255.  
  1256.     for (r = 0; r < height; r += 40)
  1257.     for (c = 0; c < width; c += 40)
  1258.     {
  1259.         Move(rp, 0L, (LONG) r);
  1260.         Draw(rp, (LONG) c, 0L);
  1261.     }
  1262. }
  1263.  
  1264. #endif
  1265.  
  1266. struct  Window * getNewWind(left, top, width, height, flg, iflg)
  1267. SHORT   left, top, width, height;
  1268. ULONG   flg, iflg;
  1269. {
  1270.     struct  Window  *OpenWindow();
  1271.     struct  NewWindow   nw;
  1272.  
  1273.     nw.LeftEdge =   (SHORT) left;
  1274.     nw.TopEdge  =   (SHORT) top;
  1275.     nw.Width    =   (SHORT) width;
  1276.     nw.Height   =   (SHORT) height;
  1277.     nw.DetailPen    =   (UBYTE) -1;
  1278.     nw.BlockPen =   (UBYTE) -1;
  1279.     nw.IDCMPFlags   =   (ULONG) iflg;
  1280.  
  1281.     nw.Flags    =   (ULONG) flg;
  1282.  
  1283.     nw.FirstGadget  =   (struct Gadget *)   NULL;
  1284.     nw.CheckMark    =   (struct Image *)    NULL;
  1285.     nw.Title    =   (UBYTE *)   " Dual Playfield Mole ";
  1286.     nw.Screen   =   (struct Screen *)   NULL;
  1287.     nw.BitMap   =   (struct BitMap *)   NULL;
  1288.     nw.MinWidth =   (SHORT) 50;
  1289.     nw.MinHeight=   (SHORT) 30;
  1290.     /* work around bug  */
  1291.     nw.MaxWidth =   (SHORT) nw.Width;
  1292.     nw.MaxHeight    =   (SHORT) nw.Height;
  1293.     nw.Type     =   (USHORT) WBENCHSCREEN;
  1294.  
  1295.     return ((struct Window *) OpenWindow(&nw));
  1296. }
  1297.  
  1298.  
  1299.  
  1300.  
  1301. 12.  MASKED BOOLEAN GADGET EXAMPLE
  1302.  
  1303. /**************************************************************************
  1304.  * Example code fragment for Masked Boolean Gadget
  1305.  *
  1306.  * copyright Commodore-Amiga, Inc., May 1986.  use at will
  1307.  * author: jim mackraz (amiga!jimm)
  1308.  ***************************************************************************/
  1309.  
  1310. /* come up with a mask of your choice */
  1311. extern UWORD testgmask[];       /* single Image plane, used here as both
  1312.                                    as mask and image */
  1313.  
  1314. /* you probably want a fancier (multi-color) image */
  1315. struct Image testgimage = {
  1316.     0, 0, 32, 32, 1,
  1317.     testgmask,  /* using same bit-plane for image as for mask */
  1318.     0x01, 0x00, NULL
  1319.     };
  1320.  
  1321. struct BoolInfo testboolinfo = {
  1322.     BOOLMASK,   /* this extension is for masked boolean values */
  1323.     testgmask,  /* a single bit plane */
  1324.     0           /* reserved */
  1325.     };
  1326.  
  1327. struct Gadget testgadget = {
  1328.     NULL, 50, 50, 32, 32,
  1329.     GADGHCOMP | GADGIMAGE | SELECTED,
  1330.     GADGIMMEDIATE | RELVERIFY | TOGGLESELECT | BOOLEXTEND,      /* NEW */
  1331.     BOOLGADGET,
  1332.     &testgimage,
  1333.     NULL,
  1334.     NULL,       /* text */
  1335.     0,          /* mutual exclude */
  1336.     &testboolinfo,                                              /* NEW */
  1337.     123,
  1338.     NULL
  1339.     };
  1340.  
  1341.  
  1342.